package main

import (
	"context"
	"fmt"
	"time"
)

func monitor(ctx context.Context, number int) {
	for {
		select {
		case <-ctx.Done():
			fmt.Printf("监控器%v，监控结束。\n", number)
			return
		default:
			fmt.Printf("监控器%v，正在监控中...\n", number)
			time.Sleep(2 * time.Second)
		}
	}
}

func main() {
	//ctx01, cancel := context.WithCancel(context.Background()) //这里和上例是一样的

	//把ctx01，作为父context传入。这样ctx02就有了deadLine超时功能.这就是context的继承
	//本例是，超过4秒未完成，就强制结束
	//ctx02, cancel := context.WithDeadline(ctx01, time.Now().Add(4*time.Second))

	//timeOut的用法，和deadLine类似，传入是相对时间，而非时间戳
	ctx02, cancel := context.WithTimeout(context.Background(), 4*time.Second)
	defer cancel()

	for i := 1; i <= 5; i++ {
		go monitor(ctx02, i)
	}

	//因为这里等了5秒，也就是说，没有在4秒内完成。所以会强制结束协程。
	time.Sleep(5 * time.Second)
	if ctx02.Err() != nil {
		fmt.Println("监控器取消的原因: ", ctx02.Err())
	}

	fmt.Println("主程序退出！！")
}
